package com.wb.structual.proxy;

import lombok.Data;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author 魏彪
 */
public class ProxyTest01 {
    public static void main(String[] args) throws ParseException {
        // 静态代理
//        Proxy proxy = new Proxy(new RealSubject());
//        proxy.request();

        // JDK动态代理
//        JdkMeiPo jdkMeiPo = new JdkMeiPo();
//        IPerson iPerson = jdkMeiPo.getInstance(new Customer());
//        iPerson.findLove();

        // 实际应用
        Order order = new Order();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        Date date = sdf.parse("2023/11/11");
        order.setCreateDt(date.getTime());

        OrderServiceStaticProxy staticProxy = new OrderServiceStaticProxy(new OrderService());
        staticProxy.createOrder(order);
    }
}

/**
 * 代理模式通用写法(静态代理)
 */
// 抽象主题角色
interface ISubject {
    void request();
}

// 代理主题角色
class Proxy implements ISubject {

    private ISubject subject;

    public Proxy(ISubject subject) {
        this.subject = subject;
    }

    @Override
    public void request() {
        before();
        subject.request();
        after();
    }

    public void before() {
        System.out.println("方法执行之前");
    }

    public void after() {
        System.out.println("方法执行之后");
    }
}

// 真实主题角色
class RealSubject implements ISubject {

    @Override
    public void request() {
        System.out.println("真实调用");
    }
}

/**
 * 动态代理
 */
interface IPerson {
    void findLove();
}

class JdkMeiPo implements InvocationHandler {

    private IPerson target;

    public IPerson getInstance(IPerson target) {
        this.target = target;
        Class<? extends IPerson> clazz = target.getClass();
        return (IPerson) java.lang.reflect.Proxy.newProxyInstance(clazz.getClassLoader()
                , clazz.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(this.target, args);
        after();
        return result;
    }

    private void before() {
        System.out.println("方法执行之前");
    }

    private void after() {
        System.out.println("方法执行之后");
    }
}

class Customer implements IPerson {
    @Override
    public void findLove() {
        System.out.println("符合客户要求的");
    }
}

/**
 * 三层架构中的静态代理
 */
@Data
class Order {
    private Object orderInfo;
    private Long createDt;
    private String id;
}

class OrderDao {
    public int insert(Order order) {
        System.out.println("OrderDao创建Order成功!");
        return 1;
    }
}

interface IOrderService {
    int createOrder(Order order);
}

class OrderService implements IOrderService {

    private final OrderDao orderDao = new OrderDao();

    @Override
    public int createOrder(Order order) {
        return orderDao.insert(order);
    }
}

class DynamicDataSourceEntry {
    public final static String DEFAULT_SOURCE = null;
    private final static ThreadLocal<String> local = new ThreadLocal<>();

    // 清空数据源
    public static void clear() {
        local.remove();
    }

    // 获取当前正在使用的数据源名字
    public static String get() {
        return local.get();
    }

    // 还原当前切换的数据源
    public static void restore() {
        local.set(DEFAULT_SOURCE);
    }

    public static void set(String source) {
        local.set(source);
    }

    public static void set(int year) {
        local.set("DB_" + year);
    }
}

// 创建切换数据源的代理类

class OrderServiceStaticProxy implements IOrderService {

    private SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");

    private IOrderService orderService;

    public OrderServiceStaticProxy(IOrderService orderService) {
        this.orderService = orderService;
    }

    @Override
    public int createOrder(Order order) {
        before();
        // 核心代码
        Long createDt = order.getCreateDt();
        int dbRouter = Integer.parseInt(yearFormat.format(new Date(createDt)));
        System.out.println("静态代理类自动分配到【DB_" + dbRouter + "】数据源处理数据");
        DynamicDataSourceEntry.set(dbRouter);
        orderService.createOrder(order);
        after();
        return 0;
    }

    private void before() {
        System.out.println("方法执行之前");
    }

    private void after() {
        System.out.println("方法执行之后");
    }
}